#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

#define handlle_error(cmd,result){  \
    if (result < 0)                 \
    {                               \
        perror(cmd);                \
        return -1;                  \
    }                               \
}   

void * read_and_write_thread(void * arg){
    int fd = *(int *)arg;
    char *buf = malloc(1024);
    ssize_t count;
    while ((count = recv(fd,buf,1024,0)) > 0)
    {
        printf("接收到文件描述符%d的客户端发送的消息%s\n",fd,buf);

        send(fd,"接收到了\n",1024,0);
    }
    if (count < 0)
    {
        perror("recv");
        shutdown(fd,SHUT_RDWR);
        close(fd);
        free(buf);
        pthread_exit(NULL);
    }
    
    printf("文件描述符%d的客户端关闭连接\n",fd);
    shutdown(fd,SHUT_RDWR);
    close(fd);
    free(buf); 
}

int main(int argc, char const *argv[])
{
    struct sockaddr_in server_addr,client_addr;
    int sock_fd,acc_fd,tmp_result,pid;
    pthread_t read_and_write_thread_t;
    memset(&server_addr,0,sizeof(server_addr));
    memset(&client_addr,0,sizeof(client_addr));

    // 1.赋值
    server_addr.sin_family = AF_INET;
    inet_pton(AF_INET,"192.168.10.150",&server_addr.sin_addr);
    server_addr.sin_port = htons(6666);

    // 2.创建socker
    sock_fd = socket(AF_INET,SOCK_STREAM,0);
    handlle_error("socket",sock_fd);

    // 3. 绑定地址
    tmp_result = bind(sock_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
    handlle_error("bind",tmp_result);

    // 4. 开启监听
    listen(sock_fd,1024);

    while (1)
    {
        socklen_t size = sizeof(client_addr);
        acc_fd = accept(sock_fd,(struct sockaddr *)&client_addr,&size);
        handlle_error("accept",acc_fd);
        printf("服务端 %s:%d接收到客户端%s:%d的文件描述符%d连接\n",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port),inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port),acc_fd);
        pthread_create(&read_and_write_thread_t,NULL,read_and_write_thread,&acc_fd);
    }

    return 0;
}
